var cdee = (function () {

    var self = this;
    return {




        forEachElm: function (nodeList, callBack, self) {
            [].slice.call(nodeList).forEach(callBack);
        },

        toType: function (obj) {
            return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
        },

        /*
         "[module]": function () {
         console.log('--------------------[module]-----------------------');
         },
         */

        findValue: function (map, key) {
            for (m in map) {
                if (m == key) return map[m];
            }
            return null;
        },

        findFunction: function (term) {

            if (cdee[term] !== undefined)
                return term;

            for (var func in cdee) {
                if ((func + "#").charAt(0) === (term + "@").charAt(0)) {
                    return func;
                }
                ;
            }
            ;
            return null;
        },


        "[]": function (term, elm, expr, model, key) {
            console.log("iterating " + term);
            var expressionValue = cdee.findValue(expr, term);
            console.log("arg expresssion:" + term + " = " + JSON.stringify(expressionValue));
            var iterationSet = eval(term);
            var subExpr = expr[term];
            var m = model;
            for (var i in iterationSet) {
                console.log("#" + m + " " + JSON.stringify(subExpr));
                cdee.produce(term, elm, subExpr, m, iterationSet[i]);
            }
        },

        "()": function (term, elm, expr, model, key) {
            console.log("iterating " + term);
            var expressionValue = cdee.findValue(expr, term);
            var variable = term.replace("(", "").replace(")", "");
            console.log("arg expresssion:" + term + " = " + JSON.stringify(expressionValue));
            var iterationSet = eval(variable);
            var subExpr = expr[term];
            var m = model;

            console.log("iteration type:" + cdee.toType(iterationSet));
            //Geen strings als charater arrays interpreteren
            if (cdee.toType(iterationSet) === "string") {
                iterationSet = [iterationSet];
            }
            for (var i in iterationSet) {
                console.log("#" + i + " " + JSON.stringify(subExpr));
                cdee.produce(term, elm, subExpr, m, iterationSet[i]);
            }
        },

        "*": function (term, elm, expr, model, key) {
            console.log("for all:" + JSON.stringify(model));
            var subExpr = expr[term];
            for (m in model) {
                console.log("#" + m + " " + JSON.stringify(subExpr));
                cdee.produce(term, elm, subExpr, model[m], m);
            }
        },

        "(model)": function (term, elm, expr, model, key) {
            console.log("for all:" + JSON.stringify(model));
            var subExpr = expr[term];
            for (m in model) {
                console.log("#" + m + " " + JSON.stringify(subExpr));
                cdee.produce(term, elm, subExpr, model[m], m);
            }
        },



        "(childs)": function (term, elm, expr, model, key) {
            //console.log("for all child elements:" + JSON.stringify(elm.children));
            var subExpr = expr[term];
            var children = elm.children;
            for (var i = 0; i < elm.children.length; i++) {
                console.log("#" + i + " " + JSON.stringify(subExpr));
                cdee.produce(term, elm.children.item(i), subExpr, model, i);
            }
        },

        "$": function (term, elm, expr, model, key) {

            var property = term.substring(1);
            var expressionValue = cdee.findValue(expr, term);
            console.log("setting property: " + property + "=" + expressionValue);
            elm[property] = eval(expressionValue);
        },

        "@": function (term, elm, expr, model, key) {

            var attribute = term.substring(1);
            var expressionValue = cdee.findValue(expr, term);
            var value = eval(expressionValue);
            console.log("adding attribute " + attribute + "=" + value);
            elm.setAttribute(attribute, value);
            var handler = function (target) {
                return function () {
                    console.log('resize:' + target.id);
                    var h = (window.innerHeight - value);
                    if (h < 0) h = 0;
                    target.style.height = h + 'px'
                }
            };
            if ("window-bottom" === attribute) {
                console.log("handler=" + handler);
                var resizer = handler(elm);
                window.addEventListener("resize", resizer, false);
                resizer();
            }
        },

        "+": function (term, elm, expr, model, key) {
            var expressionValue = cdee.findValue(expr, term);
            var listeners = eval(expressionValue);
            for (eventName in listeners) {
                var listener = listeners[eventName];
                console.log("adding eventListener: " + eventName + "=" + listener);
                elm.addEventListener(eventName, listener);
            }
        },

        //function for creating elements <>
        "<>": function (term, elm, expr, model, key) {
            // element declaration

            console.log("creating " + term);
            var expressionValue = cdee.findValue(expr, term);
            console.log("arg expresssion:" + term + " = " + JSON.stringify(expressionValue));

            var tag = term.replace("<", "").replace(">", "").replace(/\d/g,"");
            var child = (document.createElement(tag));
            elm.appendChild(child);
            if (expressionValue === "text") {
                console.log("adding text: " + term);
                child.textContent = "" + model;
            } else if (cdee.toType(expressionValue) === "string") {
                var value = eval(expressionValue);
                console.log("adding expression value: " + eval(expressionValue));
                child.textContent = "" + value;

            } else {
                console.log("parent: " + child.tagName);
                cdee.produce(term, child, expressionValue, model, key);
            }
        },


        produce: function (term, element, expression, model, key) {

            var expr = expression;
            var elm = element;
            console.log("--------------produce------------");
            console.log("term        : " + term);
            console.log("element name: " + elm.tagName);
            console.log("expression:   " + JSON.stringify(expr));
            console.log("model data :  " + JSON.stringify(model));
            console.log("key: " + key);

            var produce = cdee.produce;

            var toType = cdee.toType;

            var type = toType(expr);

            //var isString = function(expr){return ( toType(expr)=== "string");};


            console.log("type:   " + type);

            if (type === "string") {
                expr = [expr];

            }
            ;

            for (term in expr) {
                console.log("term: " + term);
                var func = cdee.findFunction(term);
                if (func != null) {
                    //if a function was found en executed
                    console.log("function for:   " + term + " = " + JSON.stringify(func));
                    cdee[func](term, elm, expr, model, key);


                } else {
                    console.log("Error unknown function" + term);
                    return;
                }

            }


        },


        process: function (elm, index, elms) {
            var cdeeName = elm.getAttribute("data-cdee");
            var modelName = elm.getAttribute("data-model");

            console.log("element-id: " + elm.id);
            console.log("cdeeName: " + cdeeName);
            console.log("modelName: " + modelName);
            var expression = eval(cdeeName);
            var model = eval(modelName);


            console.log("expresssion: " + cdeeName + "=" + JSON.stringify(expression));
            console.log("model data : " + modelName + "=" + JSON.stringify(model));

            cdee.produce("", elm, expression, model);

        },


        execute: function () {
            //alert('hi');
            var elms = document.querySelectorAll("[data-cdee]");
            this.forEachElm(elms, this.process);

        }
    }
}());

cdee.form = {"<TABLE>":{"(model)":{"<TR>":{"<TD1>":"key", "<TD>":{"<input>":{"@value":"model"}}}}}};
cdee.list = {"(model)":{"<li>":"model"}};
